Skip to content

Add lambda.DurableFunction blueprint (vs2026)#2445

Open
GarrettBeatty wants to merge 5 commits into
durabletesting2from
gcbeatty/durable-function-blueprint
Open

Add lambda.DurableFunction blueprint (vs2026)#2445
GarrettBeatty wants to merge 5 commits into
durabletesting2from
gcbeatty/durable-function-blueprint

Conversation

@GarrettBeatty

@GarrettBeatty GarrettBeatty commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Provides two dotnet new templates under Blueprints/BlueprintDefinitions/vs2026 for Lambda durable execution workflows, following the existing lambda.* / serverless.* convention (e.g. SimpleS3Function / SimpleS3FunctionServerless):

Template Programming model Deploys via Ships
lambda.DurableFunction Static wrapper (DurableFunction.WrapAsync), class-library dotnet lambda deploy-function no CloudFormation
serverless.DurableFunction Annotations ([LambdaFunction] + [DurableExecution]) dotnet lambda deploy-serverless serverless.template

Both target the managed dotnet10 runtime (durable execution requires dotnet10) and scaffold the same sample ProcessOrder workflow demonstrating the core durable primitives:

  • StepAsync — checkpointed step
  • StepAsync + RetryStrategy.Exponential with StepSemantics.AtMostOncePerRetry
  • WaitAsync — suspend timer (no compute charge while suspended)
  • RunInChildContextAsync — grouping related steps

Each ships a test project that drives the workflow locally via Amazon.Lambda.DurableExecution.Testing (no AWS resources needed). vs2026 only (matches the existing layout convention).

Why two templates

The original single blueprint was labeled lambda.DurableFunction but shipped a serverless.template and deployed via deploy-serverless — a naming/convention mismatch. This splits it so the lambda.* name actually deploys straight to Lambda, and the CloudFormation path keeps its own serverless.* name.

Using the templates

lambda.DurableFunction — deploy straight to Lambda

dotnet new lambda.DurableFunction --name MyDurableApp
cd MyDurableApp/src/MyDurableApp
dotnet lambda deploy-function
  • Class-library static-wrapper model: Handler delegates to DurableFunction.WrapAsync<OrderRequest, OrderResult>(ProcessOrder, …); the serializer is declared with [assembly: LambdaSerializer(typeof(DefaultLambdaJsonSerializer))]. No Main, no [DurableExecution], no serverless.template.
  • aws-lambda-tools-defaults.json carries function-runtime: dotnet10, the Assembly::Type::Method function-handler, and durable-execution-timeout.
  • When deploy-function creates the execution role for you, it auto-attaches AWSLambdaBasicDurableExecutionRolePolicy (the checkpoint permissions). If you pass --function-role, attach that policy yourself.
  • Requires the deploy-function durable support from aws-extensions-for-dotnet-cli PR #447 (the durable-execution-timeout switch + IAM auto-attach). Until that ships in a released Amazon.Lambda.Tools, deploy-function won't apply the durable config.

serverless.DurableFunction — deploy via CloudFormation

dotnet new serverless.DurableFunction --name MyDurableApp
cd MyDurableApp/src/MyDurableApp
dotnet lambda deploy-serverless
  • Annotations model: annotate the workflow with [LambdaFunction] + [DurableExecution]. The source generator emits the handler wrapper and keeps serverless.template in sync — DurableConfig plus the AWSLambdaBasicDurableExecutionRolePolicy managed policy.
  • No CLI dependency beyond a published Amazon.Lambda.Annotations that supports [DurableExecution].

Run the local tests (either template)

dotnet test

Testing

  • ✅ Both template projects build on net10.0; both test projects pass (2/2 each), no warnings.
  • lambda.DurableFunction instantiated (placeholder substitution) and built against the published durable preview packages.
  • End-to-end on real AWS (managed dotnet10): deployed the instantiated lambda.DurableFunction with the PR Auto-attach durable execution IAM policy in deploy-function aws-extensions-for-dotnet-cli#447 CLI build → DurableConfig.ExecutionTimeout set, AWSLambdaBasicDurableExecutionRolePolicy auto-attached to the tool-created role, and the workflow ran to SUCCEEDED (all six operations checkpointed, including the WaitAsync suspend/resume). Resources torn down afterward.

Notes

  • lambda.DurableFunction is gated on aws-extensions-for-dotnet-cli PR #447 landing in a released Amazon.Lambda.Tools.
  • Amazon.Lambda.DurableExecution / .Testing are preview packages; the templates reference 0.1.1-preview / 0.0.1-preview. Restores once those are published (or via a local feed).
  • Blueprint-only change — no .autover change file needed (autover tracks Libraries/src projects only).

Adds a new 'dotnet new' template (shortName: lambda.DurableFunction) under
Blueprints/BlueprintDefinitions/vs2026 that scaffolds a Lambda durable
execution workflow using the Annotations class-library programming model on
the managed dotnet10 runtime.

The sample workflow demonstrates the core durable primitives: StepAsync, a
step with an exponential RetryStrategy and AtMostOncePerRetry semantics,
WaitAsync (suspend timer), and RunInChildContextAsync. The generated
serverless.template includes DurableConfig and the
AWSLambdaBasicDurableExecutionRolePolicy managed policy. A test project drives
the workflow locally via Amazon.Lambda.DurableExecution.Testing.

Also registers the template in Blueprints/README.md.
@GarrettBeatty GarrettBeatty added the Release Not Needed Add this label if a PR does not need to be released. label Jun 26, 2026
<PackageReference Include="Amazon.Lambda.Core" Version="3.1.1" />
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="3.0.0" />
<PackageReference Include="Amazon.Lambda.Annotations" Version="2.0.1" />
<PackageReference Include="Amazon.Lambda.DurableExecution" Version="0.1.1-preview" />

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will update to ga version once released

<ItemGroup>
<PackageReference Include="Amazon.Lambda.Core" Version="3.1.1" />
<PackageReference Include="Amazon.Lambda.TestUtilities" Version="4.1.0" />
<PackageReference Include="Amazon.Lambda.DurableExecution.Testing" Version="0.0.1-preview" />

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this pr isnt merged yet, i tested with local nuget feed.


  # 1. Pack the three required packages into a local feed
  FEED=/tmp/durable-feed && mkdir -p "$FEED"
  cd Libraries/src/Amazon.Lambda.Annotations            && dotnet pack -c Release -o "$FEED"
  cd ../Amazon.Lambda.DurableExecution                  && dotnet pack -c Release -o "$FEED"
  cd ../Amazon.Lambda.DurableExecution.Testing          && dotnet pack -c Release -o "$FEED"

  # 2. Install the template from the blueprint folder
  cd <repo>/Blueprints/BlueprintDefinitions/vs2026/DurableFunction/template/src/BlueprintBaseName.1
  dotnet new install .    # or install from the .template.config location

  # 3. Instantiate into a scratch dir
  mkdir /tmp/dtest && cd /tmp/dtest
  dotnet new lambda.DurableFunction --name MyOrders

  # 4. Build + test against the local feed
  dotnet test --source "$FEED" --source https://api.nuget.org/v3/index.json

@GarrettBeatty GarrettBeatty marked this pull request as ready for review June 29, 2026 17:02
@GarrettBeatty GarrettBeatty requested review from a team as code owners June 29, 2026 17:02
@GarrettBeatty GarrettBeatty requested review from normj and philasmar and removed request for a team June 29, 2026 17:02
@@ -0,0 +1,39 @@
{

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intentionally only added to vs2026. didnt feel like it was worth adding to 2024 folder since dotnet8 will be end of life soon

@GarrettBeatty

Copy link
Copy Markdown
Contributor Author

The test project isn't actually bundled when doing a new project (same with other projects) but adding here to be consistent

@normj normj left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pattern of the template library is templates that start with the lambda. prefix deploy directory to Lambda. For example using the dotnet lambda deploy-function command. For templates that deploy via CloudFormation start with serverless. and you would deploy via the dotnet lambda deploy-serverless command.

I suggest we have 2 templates. One that goes directly to Lambda and uses the static wrapper method instead of annotations so it can be deploy straight to Lambda. Then a second serverless.* template that is what you have here.

@normj

normj commented Jun 30, 2026

Copy link
Copy Markdown
Member

The test project isn't actually bundled when doing a new project (same with other projects) but adding here to be consistent

The test project is still useful when you create the template via Visual Studio.

@philasmar philasmar left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approving assuming you address norm's feedback

The single DurableFunction blueprint was labeled `lambda.DurableFunction` but
shipped a serverless.template and deployed via `deploy-serverless` (the
Annotations model) — a naming/convention mismatch. Follow the
SimpleS3Function / SimpleS3FunctionServerless pattern and provide both:

- DurableFunction (lambda.DurableFunction): deploys straight to Lambda with
  `dotnet lambda deploy-function`. Uses the static-wrapper, class-library
  programming model (DurableFunction.WrapAsync + [assembly: LambdaSerializer],
  no [DurableExecution], no serverless.template). aws-lambda-tools-defaults.json
  carries function-handler/function-runtime and the new durable-execution-timeout
  key. (Requires the deploy-function durable support from
  aws-extensions-for-dotnet-cli PR #447.)

- DurableFunctionServerless (serverless.DurableFunction): the existing
  Annotations + serverless.template blueprint, relabeled to the serverless.*
  identity and deployed via `dotnet lambda deploy-serverless`.

Both build and their test projects pass. The lambda.DurableFunction variant was
verified end-to-end on the managed dotnet10 runtime (DurableConfig set, durable
IAM policy auto-attached, workflow runs to SUCCEEDED).
@GarrettBeatty

Copy link
Copy Markdown
Contributor Author

@normj updated to have two templates and i retested both

@GarrettBeatty GarrettBeatty requested a review from normj June 30, 2026 15:51
@GarrettBeatty

Copy link
Copy Markdown
Contributor Author

aws/aws-extensions-for-dotnet-cli#447 needs to be merged and released first

@GarrettBeatty GarrettBeatty removed the Release Not Needed Add this label if a PR does not need to be released. label Jun 30, 2026
Durable functions are invoked with a qualified function reference and a durable execution name:

```bash
dotnet lambda invoke-function BlueprintBaseName.1 --payload '{"OrderId":"order-123","Items":["sku-1","sku-2"]}'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add the --invoke-model switch for Durable functions?

The workflow validates the order, charges payment, waits out a short settlement period, ships the
order in a child context, and returns the result.

## Test

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't have this section since the test project will only exist if the create the project via Visual Studio. You could have a more general section about how to test and and pointing out the Amazon.Lambda.DurableExecution.Testing project. Just don't say there is a Test project.

## Test

The included test project drives the workflow locally with the
`Amazon.Lambda.DurableExecution.Testing` runner — no AWS resources required:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be careful calling it a runner or make it more clear that it isn't a test runner but a durable functions runner. That sounds like this is our own flavor of xUnit or mstest which are test runners.

"display-name": "Durable Function",
"system-name": "DurableFunction",
"description": "A durable execution workflow that checkpoints every step, so it can be suspended during waits and resumed after a crash without re-running completed work. Deploys straight to Lambda with the 'dotnet lambda deploy-function' command.",
"sort-order": 130,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This controls the order the blueprint shows up in the VS blueprint dialog

Image

130 would basically put this at the bottom where users would have to scroll. Looking at the other sort orders if you set this to 124 it would be next to the PowerTools template and before all of the "Simple" templates.

<ItemGroup>
<PackageReference Include="Amazon.Lambda.Core" Version="3.1.1" />
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="3.0.0" />
<PackageReference Include="Amazon.Lambda.Annotations" Version="2.0.1" />

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you want version 2.1.0 of Annotations where it looks like the DurableExecution attribute was added.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes your right, i think i built it locally which is why it picked up an old version. will update

The workflow validates the order, charges payment, waits out a short settlement period, ships the
order in a child context, and returns the result.

## Test

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comments as the previous README about the test section

After deploying, invoke the function with a sample order payload:

```bash
dotnet lambda invoke-function BlueprintBaseName.1 --payload '{"OrderId":"order-123","Items":["sku-1","sku-2"]}'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment about using --invoke-mode.

Also BlueprintBaseName.1 is unlikely to the function name because CloudFormation is going generate the function name. So you might need to give some context on how to find the function name.

"display-name": "Durable Function",
"system-name": "DurableFunction",
"description": "A durable execution workflow that checkpoints every step, so it can be suspended during waits and resumed after a crash without re-running completed work.",
"sort-order": 130,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest setting sort-order to 120 to put in with the Annotations template in the VS wizard.

Image

@normj

normj commented Jun 30, 2026

Copy link
Copy Markdown
Member

Can you also add the new blueprints to this list in the buildtools targets? It is at target I use to sanity check that all of the blueprints can be instantiated and compiled. https://github.com/aws/aws-lambda-dotnet/blob/master/buildtools/build.proj#L70

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants